package Server.Agent;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import Server.Model.Base.NotifierBase;
import Server.Model.Base.ReceiveMessage;
import Server.Model.Base.SHMUser;
import Server.Model.Hall.dthall;
import io.netty.channel.ChannelHandlerContext;


public class GameAgent extends ChannelInboundHandler {
	public ChannelHandlerContext mCtx;
	@Override
	public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
		super.channelRegistered(ctx);
		CurConnection++;
		if(MaxConnection < CurConnection)
		{
			MaxConnection = CurConnection;
		}
		mCtx = ctx;
		onClientConnect();
	}
			
	@Override
	public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
		super.channelUnregistered(ctx);
		CurConnection--;
		
		if(CurConnection < 0)
		{
			System.out.println("OH");
		}
		
		int cntAgent = agents.size();
		System.out.printf("%d OnDisconnect :\t Connection: %d | %d_%d\n",MaxConnection,CurConnection,CID,cntAgent);
		
		onClientClose();
	}

	public static NotifierBase notifier = new NotifierBase();
	public static Map<Integer,GameAgent> agents = new HashMap<>();
	public static int __id = 1;
	public static int MaxConnection = 0;
	public static int CurConnection = 0;
	
	public Long m_heartTime;
	
	public int CID = 0;	
	public SHMUser user;	
	public SHMUser getUser() {
		return user;
	}
	public String getIP(){
		String ip = "";
		try
		{
			ip = super.IP();
			if (StringUtils.isEmpty(ip)) {
				return "";
			}	
		}catch(Exception e)
		{
			e.printStackTrace();
		}

		return ip;
	}
	public Integer getCID()
	{
		return CID;
	}	
	public Integer getUID()
	{
		if(user != null)
		{
			return user.getUid();
		}
		return 0;
	}
	public static void setUser(Integer _Uid, SHMUser shmUser) {
		GameAgent agent = agents.get(_Uid);
		if (agent!=null) {
			agent.setUser(shmUser);
		}
	}
	public void setUser(SHMUser user) {
		this.user = user;
	}
 
    public static void add_client(GameAgent agent){  
    	agents.put(agent.CID, agent);	
    }  

    public static void del_client(GameAgent agent){  
		Iterator<Map.Entry<Integer, GameAgent>> iterAgent = agents.entrySet().iterator();  
        while(iterAgent.hasNext()){  
            Map.Entry<Integer, GameAgent> entry=iterAgent.next();  
            GameAgent value=entry.getValue();  
            if(value == agent){  
            	iterAgent.remove();        //OK   
            }  
        }  
    }
    public static GameAgent find_client(int in_CID)
    {
    	if(agents.containsKey(in_CID) )
    	{
    		return agents.get(in_CID);
    	}
    	return null;
    }
	public GameAgent() {
		CID = __id++;
		agents.put(CID, this);	
		m_heartTime = System.currentTimeMillis();

		try
		{
			KickDeadSessions();
		}catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	public void Disconnect()
	{
		if(mCtx != null)
		{
			mCtx.disconnect();
			mCtx = null;
		}
	}
	public static void Send(int CID,String msg){
		GameAgent agent = agents.get(CID);
		
		if (agent!=null) {
			agent.SendMessage(msg);
			//System.out.println(msg);
		}
	}
	public static void Broadcast(int CID,String msg){
		try
		{
			Iterator<Map.Entry<Integer, GameAgent>> it = agents.entrySet().iterator();
	        while(it.hasNext()){  
	            Map.Entry<Integer, GameAgent> entry=it.next();  
	            GameAgent agent=entry.getValue();  
	            if(agent != null){
	            	agent.SendMessage(msg);
	            }  
	        }
		}catch(Exception e)
		{
			e.printStackTrace();
		}	
	}	
	@Override
	public void onMessage(String message) {
		try {
			m_heartTime = System.currentTimeMillis();
			notifier.Notify(new ReceiveMessage(message,this));
			/*
			JSONObject json = new JSONObject(message);
			System.out.print(json.get("command"));
			dthall.getInstance().OnRecv(this,json);
			*/
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void onClientConnect() {
		add_client(this);
		try {
			System.out.printf("%d Accept Session From IP : %s \tConnection: %d\n", MaxConnection, getIP(),agents.size());
		} catch (Exception e) {
			e.printStackTrace();
		}		
	}
	public void onClientClose() {		
		del_client(this);

		dthall.getInstance().OnClientClose(this);
		m_heartTime = System.currentTimeMillis();
		
	}

	public int getUid() {
		if (user != null) {
			return user.m_lUid;
		}
		return 0;
	}
	public boolean m_bRemove = false;
	public void Remove()
	{
		m_bRemove = true;
	}	
	public boolean ShouldBeRemoved()
	{
		return m_bRemove;
	}
	public boolean isTimeOut()
	{
		if(m_heartTime > 0 && System.currentTimeMillis() - m_heartTime > 3600*1000)
		{
			return true;
		}
		return false;
	}	

	public static synchronized void KickDeadSessions()
	{
		try
		{
			Iterator<Map.Entry<Integer, GameAgent>> it = agents.entrySet().iterator();
	        while(it.hasNext()){  
	            Map.Entry<Integer, GameAgent> entry=it.next();  
	            int key=entry.getKey();
	            GameAgent value=entry.getValue();  
	            if(value != null && (value.ShouldBeRemoved() || value.isTimeOut())){
	                System.out.println("remove dead agent cid: "+key);  
	                value.Disconnect();
	                it.remove();        //OK
	            }  
	        }
		}catch(Exception e)
		{
			
		}	
	}
}